package com.azier.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;

/**
 * 字节操作工具
 *
 * @author 金建强(ptma@163.com)
 * @version 2015-11-27 14:23
 */
public final class ByteUtil {

    private static final Logger LOGGER      = LoggerFactory.getLogger(ByteUtil.class);

    public static final int     SIZE_BOOL   = 1;
    public static final int     SIZE_CHAR   = 2;
    public static final int     SIZE_SHORT  = 2;
    public static final int     SIZE_INT    = 4;
    public static final int     SIZE_LONG   = 8;
    public static final int     SIZE_DOUBLE = 8;
    public static final String  HEX_DIGITS  = "0123456789ABCDEF";

    private ByteUtil() {}

    /**
     * 返回指定子字节数组在源字节数组中第一次出现的索引
     *
     * @param source 源字节数组
     * @param match 子字节数组
     * @return 返回第一次出现的索引 (未找到时返回 -1)
     */
    public static int indexOf(byte[] source, byte[] match) {
        for (int i = 0, n = source.length; i < n; i++) {
            if (startsWith(source, i, match)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * 返回指定子字节数组在源字节数组中最后一次出现的索引
     *
     * @param source 源字节数组
     * @param match 子字节数组
     * @return 返回最后一次出现的索引 (未找到时返回 -1)
     */
    public static int lastIndexOf(byte[] source, byte[] match) {
        if (source.length < match.length) {
            return -1;
        }

        for (int i = 0; i < (source.length - match.length); i++) {
            if (endsWith(source, i, match)) {
                return source.length - match.length - i;
            }
        }
        return -1;
    }

    /**
     * 源字节数组是否以指定前缀开始
     *
     * @param source 源字节数组
     * @param prefix 前缀
     * @return 源字节数组的开头与前缀相符时返回 true
     */
    public static boolean startsWith(byte[] source, byte prefix) {
        return startsWith(source, 0, new byte[] {prefix});
    }

    /**
     * 源字节数组是否以指定前缀开始
     *
     * @param source 源字节数组
     * @param prefix 前缀
     * @return 源字节数组的开头与前缀相符时返回 true
     */
    public static boolean startsWith(byte[] source, byte[] prefix) {
        return startsWith(source, 0, prefix);
    }

    /**
     * 源字节数组从指定索引开始的子字节数组是否以指定前缀开始
     *
     * @param source 源字节数组
     * @param offset 开始查找的位置(偏移量)
     * @param prefix 前缀
     * @return 源字节数组经过便宜的开头与前缀相符时返回 true
     */
    public static boolean startsWith(byte[] source, int offset, byte[] prefix) {

        if ((prefix == null) || (source == null)) {
            return false;
        }

        if (prefix.length > source.length - offset) {
            return false;
        }

        for (int i = 0, n = prefix.length; i < n; i++) {
            if (source[offset + i] != prefix[i]) {
                return false;
            }
        }
        return true;
    }

    /**
     * 源字节数组是否以指定前缀开始
     *
     * @param source 源字节数组
     * @param prefix 前缀
     * @return 源字节数组的开头与前缀相符时返回 true
     */
    public static boolean startsWith(byte[] source, List<Byte> prefix) {
        return startsWith(source, 0, prefix);
    }

    /**
     * 源字节数组从指定索引开始的子字节数组是否以指定前缀开始
     *
     * @param source 源字节数组
     * @param offset 开始查找的位置(偏移量)
     * @param prefix 前缀
     * @return 源字节数组经过便宜的开头与前缀相符时返回 true
     */
    public static boolean startsWith(byte[] source, int offset, List<Byte> prefix) {

        if ((prefix == null) || (source == null)) {
            return false;
        }

        if (prefix.size() > source.length - offset) {
            return false;
        }

        for (int i = 0, n = prefix.size(); i < n; i++) {
            if (source[offset + i] != prefix.get(i)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 源字节数组是否以指定后缀结束
     *
     * @param source 源字节数组
     * @param suffix 后缀
     * @return 是或否
     */
    public static boolean endsWith(byte[] source, byte[] suffix) {
        return endsWith(source, 0, suffix);
    }

    /**
     * 源字节数组是否以指定后缀结束
     *
     * @param source 源字节数组
     * @param rightOffset 右偏移量
     * @param suffix 后缀
     * @return 是或否
     */
    public static boolean endsWith(byte[] source, int rightOffset, byte[] suffix) {
        if (source == null || suffix == null) {
            return (source == null) && (suffix == null);
        }
        if (suffix.length > source.length) {
            return false;
        }
        int offset = source.length - suffix.length;
        for (int i = 0, n = suffix.length; i < n; i++) {
            if (source[offset + i - rightOffset] != suffix[i]) {
                return false;
            }
        }
        return true;
    }

    /**
     * 源字节数组是否以指定前缀开始， 并以指定后缀结束
     *
     * @param source 源字节数组
     * @param prefix 右偏移量
     * @param suffix 后缀
     * @return 是或否
     */
    public static boolean surroundsWith(byte[] source, byte[] prefix, byte[] suffix) {
        return startsWith(source, prefix) && endsWith(source, suffix);
    }

    /**
     * 截取指定前缀到指定后缀之间的数组， 含前缀和后缀
     *
     * @param source 源字节数组
     * @param prefix 前缀
     * @param suffix 后缀
     * @return 去掉前缀后缀后的数组
     */
    public static byte[] extract(byte[] source, byte[] prefix, byte[] suffix) {
        int leftIndex = indexOf(source, prefix);
        int lastIndex = lastIndexOf(source, suffix);
        if (leftIndex < 0) {
            leftIndex = 0;
        }
        if (lastIndex < 0) {
            lastIndex = source.length;
        } else {
            lastIndex += suffix.length;
        }
        return subBytes(source, leftIndex, lastIndex);
    }

    /**
     * 两个数组是否相等, 按索引顺序比较每个字节
     *
     * @param source 源字节数组
     * @param match 目标字节数组
     * @return 是或否
     */
    public static boolean equals(byte[] source, byte[] match) {
        return match.length == source.length && startsWith(source, 0, match);
    }

    /**
     * 去除两边特定的字节
     *
     * @param source 源字节数组
     * @param trimByte 特定字节
     * @return 去掉前缀后缀后的数组
     */
    public static byte[] trim(byte[] source, byte trimByte) {
        byte[] bs = source;
        int i = 0;
        for (; i < bs.length; i++) {
            if (bs[i] != trimByte) {
                break;
            }
        }
        bs = subBytes(bs, i, bs.length - i);
        int j = bs.length - 1;
        for (; j >= 0; j--) {
            if (bs[j] != trimByte) {
                break;
            }
        }
        bs = subBytes(bs, 0, j + 1);
        return bs;
    }

    /**
     * 从源字节数组中复制指定范围的内容到目标数组
     *
     * @param source 源字节数组
     * @param srcBegin 开始索引(含)
     * @param srcEnd 结束索引(不含)
     * @param destination 目标字节数组
     * @param dstBegin 目标字节数组索引偏移量
     */
    public static void getBytes(byte[] source, int srcBegin, int srcEnd, byte[] destination, int dstBegin) {
        System.arraycopy(source, srcBegin, destination, dstBegin, srcEnd - srcBegin);
    }

    /**
     * 从源字节数组中抽取指定范围的内容到一个新的数组
     *
     * @param srcBegin 开始索引(含)
     * @param srcEnd 结束索引(不含)
     * @return 抽取的新数组
     */
    public static byte[] subBytes(byte[] source, int srcBegin, int srcEnd) {
        byte[] destination = new byte[srcEnd - srcBegin];
        getBytes(source, srcBegin, srcEnd, destination, 0);

        return destination;
    }

    /**
     * 从源字节数组中抽取从指定索引到结束的内容到一个新的数组
     *
     * @param srcBegin 开始索引(含)
     * @return 抽取的新数组
     */
    public static byte[] subBytes(byte[] source, int srcBegin) {
        return subBytes(source, srcBegin, source.length);
    }

    /**
     * 合并字节数组
     *
     * @param array1 数组1
     * @param array2 数组2
     * @return 合并后的新数组
     */
    public static byte[] concat(byte[] array1, byte[] array2) {
        if (array1 == null) {
            return ArrayUtil.clone(array2);
        } else if (array2 == null) {
            return ArrayUtil.clone(array1);
        }
        byte[] result = new byte[array1.length + array2.length];

        System.arraycopy(array1, 0, result, 0, array1.length);
        System.arraycopy(array2, 0, result, array1.length, array2.length);
        return result;
    }

    /**
     * 合并字节数组
     *
     * @param array1 数组1
     * @param array2 数组2
     * @return 合并后的新数组
     */
    public static byte[] combine(byte[] array1, byte[] array2) {
        return concat(array1, array2);
    }

    /**
     * 字节数组转十六进制字符串
     *
     * @param bytes 源字节数组
     * @param splitWithSpace 是否用空格分隔
     * @return 返回十六进制字符串
     */
    public static String toHexString(byte[] bytes, boolean splitWithSpace) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0, n = bytes.length; i < n; i++) {
            byte b = bytes[i];
            if (splitWithSpace && (i > 0)) {
                sb.append(" ");
            }
            int high = (b & 0xf0) >> 4;
            int low = b & 0x0f;
            sb.append(HEX_DIGITS.charAt(high));
            sb.append(HEX_DIGITS.charAt(low));
        }
        return sb.toString();
    }

    /**
     * 字节转十六进制字符串
     *
     * @param b 源字节
     * @return 返回十六进制字符串
     */
    public static String toHexString(byte b) {
        return toHexString(new byte[] {b}, false);
    }

    /**
     * 字节数组转十六进制字符串
     *
     * @param bytes 源字节数组
     * @return 返回十六进制字符串
     */
    public static String toHexString(byte[] bytes) {
        return toHexString(bytes, true);
    }

    /**
     * 整型转换为 BCD 字节数组
     *
     * @param num 10进制数字
     * @return 字节数组
     */
    public static byte[] toBCD(long num) {
        int digits = 0;
        long numTmp = num;
        long temp = numTmp;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }

        int byteLen = digits % 2 == 0 ? digits / 2 : (digits + 1) / 2;

        byte[] bcd = new byte[byteLen];

        for (int i = 0; i < digits; i++) {
            byte tmp = (byte) (numTmp % 10);

            if (i % 2 == 0) {
                bcd[i / 2] = tmp;
            } else {
                bcd[i / 2] |= (byte) (tmp << 4);
            }

            numTmp /= 10;
        }

        for (int i = 0; i < byteLen / 2; i++) {
            byte tmp = bcd[i];
            bcd[i] = bcd[byteLen - i - 1];
            bcd[byteLen - i - 1] = tmp;
        }

        return bcd;
    }

    /**
     * BCD 字节数组转为长整形
     *
     * @param bcd BCD 形式的数组
     * @return 转换后的长整形
     */
    public static long bcdToLong(byte[] bcd) {
        return Long.parseLong(toHexString(bcd, false));
    }

    /**
     * BCD 字节数组转为整形
     *
     * @param bcd BCD 形式的数组
     * @return 转换后的整形
     */
    public static int bcdToInt(byte[] bcd) {
        return Integer.parseInt(toHexString(bcd, false));
    }

    /**
     * 字节数组转 GBK 字符串
     *
     * @param bytes 源字节数组
     * @return GBK字符串
     */
    public static String toGBKString(byte[] bytes) {
        String result;
        byte[] copyBytes = new byte[bytes.length];
        for (int i = 0, n = bytes.length; i < n; i++) {
            if (bytes[i] == 0x00) {
                copyBytes[i] = 0x20;
            } else {
                copyBytes[i] = bytes[i];
            }
        }
        try {
            result = new String(copyBytes, "GBK");
        } catch (Exception e) {
            LOGGER.trace(e.getMessage(), e);
            result = new String(copyBytes);
        }
        return result;
    }

    /**
     * GBK 字符串转字节数组
     *
     * @param str GBK 字符串
     * @param arrayLength 目标数组的长度（超出时截断， 不足时补空格）
     * @return 字节数组
     */
    public static byte[] gbkToBytes(String str, int arrayLength) {
        byte[] strBytes;
        try {
            strBytes = str.getBytes("GBK");
        } catch (Exception e) {
            LOGGER.trace(e.getMessage(), e);
            strBytes = str.getBytes();
        }
        byte[] result = new byte[arrayLength];
        for (int i = 0; i < arrayLength; i++) {
            if (i < strBytes.length) {
                result[i] = strBytes[i];
            } else {
                result[i] = 0x20;
            }
        }
        return result;
    }

    /**
     * 十六进制字符串转字节数组
     *
     * @param hexStr 十六进制字符串, 可包含空格
     * @return 字节数组
     */
    public static byte[] hexToBytes(String hexStr) {
        if (hexStr == null) {
            return new byte[0];
        }
        String str = hexStr.trim().replace(" ", "");
        int len = str.length();
        if (len == 0) {
            return new byte[0];
        }
        if ((len % 2) != 0) {
            str = '0' + str;
        }

        byte[] b = new byte[len / 2];
        try {
            for (int i = 0, n = str.length(); i < n; i += 2) {
                b[i / 2] = (byte) Integer.decode("0x" + str.substring(i, i + 2)).intValue();
            }
            return b;
        } catch (Exception e) {
            LOGGER.trace(e.getMessage(), e);
            return new byte[0];
        }
    }

    /**
     * 字节转二进制字符串
     *
     * @param b 源字节
     * @return 二进制字符串
     */
    public static String toBinaryString(byte b) {
        return toBinaryString(new byte[] {b});
    }

    /**
     * 字节数组转二进制字符串
     *
     * @param bytes 源字节数组
     * @return 二进制字符串
     */
    public static String toBinaryString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        int n = Byte.SIZE * bytes.length;
        for (int i = 0; i < n; i++) {
            sb.append((bytes[i / Byte.SIZE] << i % Byte.SIZE & 0x80) == 0 ? '0' : '1');
        }
        return sb.toString();
    }

    /**
     * 交换高4位与低4位的位置
     *
     * @param b 原始字节
     * @return byte 交换高4位与低4位后的字节值
     */
    public static byte swap(byte b) {
        int lowBits = b & 0x0F; // 获得低4位
        int highBits = b & 0xF0; // 获得高4位
        // 把低4位左移4位，变成高4位
        // 把高4位无符号右移4位，变成低4位
        // 再把两者进行位或
        int result = lowBits << 4 | highBits >>> 4;

        return (byte) result; // 强制类型转换，截取int数据的后八位
    }

    /**
     * 获取高四位
     *
     * @param b 原始字节
     * @return 高四位值
     */
    public static int getHigh4(byte b) {
        int highBits;
        highBits = b & 0xf0 >> 4;
        return highBits;
    }

    /**
     * 获取低四位
     *
     * @param b 原始字节
     * @return 低四位值
     */
    public static int getLow4(byte b) {
        return b & 0x0f;
    }

    /**
     * 计算出给定byte中的每一位, 并以一个布尔数组返回. true表示为1, false表示为0.
     *
     * @param b 单字节
     * @return 长度为8的布尔数组
     */
    public static boolean[] toBitBooleanArray(byte b) {
        boolean[] buff = new boolean[8];
        int index = 0;
        for (int i = 7; i >= 0; i--) {
            buff[index++] = ((b >>> i) & 1) == 1;
        }
        return buff;
    }

    /**
     * 计算出给定byte[]中的每一位, 并以一个布尔数组返回. true表示为1, false表示为0.
     *
     * @param bytes 原始字节数组
     * @return boolean 数组
     */
    public static boolean[] toBitBooleanArray(byte[] bytes) {
        boolean[] buff = new boolean[8 * bytes.length];
        for (int i = 0; i < bytes.length; i++) {
            for (int j = 7; j >= 0; j--) {
                buff[i * 8 + (8 - j - 1)] = ((bytes[i] >>> j) & 1) == 1;
            }
        }
        return buff;
    }

    /**
     * 返回指定字节中指定bit位, true为1, false为0. 指定的位从0-7
     *
     * @param b 单字节
     * @param index 第几位0-7
     * @return 指定bit位的布尔类型, true为1, false为0
     */
    public static boolean toBitBoolean(byte b, int index) {
        return toBitBooleanArray(b)[index];
    }

    /**
     * byte 转 bit 数组
     *
     * @param b 单字节
     * @return 长度为8的整形数组, 每一个元素只会是 0 或 1
     */
    public static int[] toBitArray(byte b) {
        int[] buff = new int[8];
        int index = 0;
        for (int i = 7; i >= 0; i--) {
            buff[index++] = (b >>> i) & 1;
        }
        return buff;
    }

    /**
     * byte[] 转 bit 数组
     *
     * @param b 字节数组
     * @return bit 数组
     */
    public static int[] toBitArray(byte[] b) {
        int[] buff = new int[8 * b.length];
        for (int i = 0; i < b.length; i++) {
            for (int j = 7; j >= 0; j--) {
                buff[i * 8 + (8 - j - 1)] = (b[i] >>> j) & 1;
            }
        }
        return buff;
    }

    /**
     * 返回指定字节中指定bit位
     *
     * @param byteValue 单字节
     * @param bitpos 第几位7-0 (从右向左)
     *
     * @return 指定bit位, 0 或 1
     */
    public static int getBit(byte byteValue, int bitpos) {
        int intValue = byteValue & 0xFF;
        return (intValue >>> bitpos) & 1;
    }

    /**
     * 设置指定字节中指定bit位
     *
     * @param byteValue 单字节
     * @param bitValue true=1, false=0
     * @param bitpos 第几位7-0 (从右向左)
     * @return 修改后的字节
     */
    public static byte setBit(byte byteValue, boolean bitValue, int bitpos) {
        int newValue;
        int intValue = byteValue & 0xFF;
        if (bitValue) {
            newValue = intValue | (1 << bitpos);
        } else {
            newValue = intValue & ~(1 << bitpos);
        }
        return (byte) (newValue & 0xFF);
    }

    /**
     * 设置指定字节中指定bit位
     *
     * @param intValue 多字节
     * @param bitValue true=1, false=0
     * @param bitpos 第几位(15-8,7-0 从右向左)
     * @return 修改后的字节
     */
    public static int setBit(int intValue, boolean bitValue, int bitpos) {
        if (bitValue) {
            return intValue | (1 << bitpos);
        } else {
            return intValue & ~(1 << bitpos);
        }
    }

    /**
     * 设置指定字节中指定bit位(大端模式，高位在前)
     *
     * @param bytes 字节数组
     * @param bitValue true=1, false=0
     * @param bitpos 第几位([...][15-8],[7-0] 从右向左)
     * @return 修改后的字节数组
     */
    public static byte[] setBit(byte[] bytes, boolean bitValue, int bitpos) {
        byte[] reverseBytes = ByteUtil.reverse(bytes);
        int byteIndex = bitpos / 8;
        int bitIndex = bitpos % 8;

        reverseBytes[byteIndex] = setBit(reverseBytes[byteIndex], bitValue, bitIndex);
        return ByteUtil.reverse(reverseBytes);
    }

    /**
     * 返回指定字节中指定bit位
     *
     * @param byteValue 单字节
     * @param bitpos 第几位0-7 (从左向右)
     * @return 指定bit位, 0 或 1
     */
    public static int getBitFromLeft(byte byteValue, int bitpos) {
        int intValue = byteValue & 0xFF;
        return (intValue >>> (8 - bitpos - 1)) & 1;
    }

    /**
     * 设置指定字节中指定bit位
     *
     * @param byteValue 单字节
     * @param bitValue true=1, false=0
     * @param bitpos 第几位0-7 (从左向右)
     * @return 修改后的字节
     */
    public static byte setBitFromLeft(byte byteValue, boolean bitValue, int bitpos) {
        int newValue;
        int intValue = byteValue & 0xFF;
        if (bitValue) {
            newValue = intValue | (1 << (8 - bitpos - 1));
        } else {
            newValue = intValue & ~(1 << (8 - bitpos - 1));
        }
        return (byte) (newValue & 0xFF);
    }

    /**
     * 字节数组转 Ansi 字符串
     */
    public static String toAnsi(byte[] b) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < b.length; i++) {
            sb.append((char) b[i]);
        }
        return sb.toString();
    }

    /**
     * 双字节转 Char, 数组长度超过 2 时只取前 2 (默认为大端模式)
     *
     * @param b 字节数组
     * @return 字符
     */
    public static char toChar(byte[] b) {
        return toChar(b, 0, ByteOrder.BIG_ENDIAN);
    }

    /**
     * 双字节转 Char, 数组长度超过 2 时只取前 2
     *
     * @param b 字节数组
     * @param order 大小端模式
     * @return 字符
     */
    public static char toChar(byte[] b, ByteOrder order) {
        return toChar(b, 0, order);
    }

    /**
     * 双字节转 Char, 数组长度超过 2 时只取前 2 (默认为大端模式)
     *
     * @param b 字节数组
     * @param offset 左偏移量
     * @return 字符
     */
    public static float toChar(byte[] b, int offset) {
        return toChar(b, offset, ByteOrder.BIG_ENDIAN);
    }

    /**
     * 双字节转 Char, 数组长度超过 2 时只取前 2
     *
     * @param b 字节数组
     * @param offset 左偏移量
     * @param order 大小端模式
     * @return 字符
     */
    public static char toChar(byte[] b, int offset, ByteOrder order) {
        if (ByteOrder.BIG_ENDIAN.equals(order)) {
            return (char) (((b[offset] & 0xFF) << 8) | (b[offset + 1] & 0xFF));
        } else {
            return (char) ((b[offset] & 0xFF) | ((b[offset + 1] & 0xFF) << 8));
        }
    }

    /**
     * Char 转双字节数组(默认为大端模式)
     *
     * @param c 字符
     * @return 双字节数组
     */
    public static byte[] toByte(char c) {
        return toByte(c, ByteOrder.BIG_ENDIAN);
    }

    /**
     * Char 转双字节数组
     *
     * @param c 字符
     * @param order 大小端模式
     * @return 双字节数组
     */
    public static byte[] toByte(char c, ByteOrder order) {
        byte[] b = new byte[SIZE_CHAR];
        if (ByteOrder.BIG_ENDIAN.equals(order)) {
            b[0] = (byte) ((c & 0xFF00) >> 8);
            b[1] = (byte) (c & 0xFF);
        } else {
            b[0] = (byte) (c & 0xFF);
            b[1] = (byte) ((c & 0xFF00) >> 8);
        }
        return b;
    }

    /**
     * 字节转整型
     *
     * @param b 字节
     * @return 整型值
     */
    public static int toInt(byte b) {
        return ((int) b) & 0xff;
    }

    /**
     * 整型转字节数组(默认为大端模式)
     *
     * @param val 整型值
     * @return 长度为 4 的字节数组
     */
    public static byte[] toBytes(int val) {
        return toBytes(val, ByteOrder.BIG_ENDIAN);
    }

    /**
     * 整型转字节数组
     *
     * @param val 整型值
     * @param order 大小端模式
     * @return 长度为 4 的字节数组
     */
    public static byte[] toBytes(int val, ByteOrder order) {
        byte[] b = new byte[SIZE_INT];
        if (ByteOrder.BIG_ENDIAN.equals(order)) {
            b[0] = (byte) (val >> 24);
            b[1] = (byte) (val >> 16);
            b[2] = (byte) (val >> 8);
            b[3] = (byte) val;
        } else {
            b[0] = (byte) val;
            b[1] = (byte) (val >> 8);
            b[2] = (byte) (val >> 16);
            b[3] = (byte) (val >> 24);
        }
        return b;
    }

    /**
     * 字节数组转整型(大端模式, 高字节在前)
     *
     * @param b 字节数组
     * @return 整型
     */
    public static int toInt(byte[] b) {
        return toInt(b, 0);
    }

    /**
     * 字节数组转整型(大端模式, 高字节在前)
     *
     * @param b 字节数组
     * @param order 大小端模式
     * @return 整型
     */
    public static int toInt(byte[] b, ByteOrder order) {
        return toInt(b, 0, order);
    }

    /**
     * 字节数组转整型(大端模式, 高字节在前)
     *
     * @param b 字节数组
     * @param offset 偏移量
     * @return 整型
     */
    public static int toInt(byte[] b, int offset) {
        return toInt(b, offset, ByteOrder.BIG_ENDIAN);
    }

    /**
     * 字节数组转整型
     *
     * @param b 字节数组
     * @param offset 偏移量
     * @param order 大小端模式
     * @return 整型
     */
    public static int toInt(byte[] b, int offset, ByteOrder order) {
        if (ByteOrder.BIG_ENDIAN.equals(order)) {
            return ((b[offset] & 0xff) << 24) | ((b[offset + 1] & 0xff) << 16) | ((b[offset + 2] & 0xff) << 8)
                    | (b[offset + 3] & 0xff);
        } else {
            return (b[offset] & 0xff) | ((b[offset + 1] & 0xff) << 8) | ((b[offset + 2] & 0xff) << 16)
                    | ((b[offset + 3] & 0xff) << 24);
        }
    }

    /**
     * 字节数组转无符号整型
     *
     * @param b 字节数组
     * @return 长整型
     */
    public static long toUnsignedInt(byte[] b) {
        return toInt(b) & 0xFFFFFFFFL;
    }

    /**
     * 字节数组转无符号整型
     *
     * @param b 字节数组
     * @param offset 偏移量
     * @return 长整型
     */
    public static long toUnsignedInt(byte[] b, int offset) {
        return toInt(b, offset) & 0xFFFFFFFFL;
    }

    /**
     * 字节数组转无符号整型
     *
     * @param b 字节数组
     * @param order 大小端模式
     * @return 长整型
     */
    public static long toUnsignedInt(byte[] b, ByteOrder order) {
        return toInt(b, order) & 0xFFFFFFFFL;
    }

    /**
     * 字节数组转无符号整型
     *
     * @param b 字节数组
     * @param offset 偏移量
     * @param order 大小端模式
     * @return 长整型
     */
    public static long toUnsignedInt(byte[] b, int offset, ByteOrder order) {
        return toInt(b, offset, order) & 0xFFFFFFFFL;
    }

    /**
     * 写入整型数到字节数组(大端模式, 高字节在前)
     *
     * @param bytes 目标字节数组
     * @param value 写入值
     */
    public static void writeInt(byte[] bytes, int value) {
        writeInt(bytes, 0, value, ByteOrder.BIG_ENDIAN);
    }

    /**
     * 写入整型数到字节数组(大端模式, 高字节在前)
     *
     * @param bytes 目标字节数组
     * @param value 写入值
     * @param order 大小端模式
     */
    public static void writeInt(byte[] bytes, int value, ByteOrder order) {
        writeInt(bytes, 0, value, order);
    }

    /**
     * 写入整型数到字节数组(大端模式, 高字节在前)
     *
     * @param bytes 目标字节数组
     * @param position 写入位置
     * @param value 写入值
     */
    public static void writeInt(byte[] bytes, int position, int value) {
        writeInt(bytes, position, value, ByteOrder.BIG_ENDIAN);
    }

    /**
     * 写入整型数到字节数组
     *
     * @param bytes 目标字节数组
     * @param position 写入位置
     * @param value 写入值
     * @param order 大小端模式
     */
    public static void writeInt(byte[] bytes, int position, int value, ByteOrder order) {
        if (ByteOrder.BIG_ENDIAN.equals(order)) {
            bytes[position] = (byte) (value >> 24);
            bytes[position + 1] = (byte) (value >> 16);
            bytes[position + 2] = (byte) (value >> 8);
            bytes[position + 3] = (byte) (value);
        } else {
            bytes[position] = (byte) (value);
            bytes[position + 1] = (byte) (value >> 8);
            bytes[position + 2] = (byte) (value >> 16);
            bytes[position + 3] = (byte) (value >> 24);
        }
    }

    /**
     * 写入整型数到字节数组(4字节, 转为无符号)
     *
     * @param bytes 目标字节数组
     * @param value 写入值
     */
    public static void writeUnsignedInt(byte[] bytes, short value) {
        writeInt(bytes, 0, value & 0xFFFF, ByteOrder.BIG_ENDIAN);
    }

    /**
     * 写入整型数到字节数组(4字节, 转为无符号)
     *
     * @param bytes 目标字节数组
     * @param value 写入值
     */
    public static void writeUnsignedInt(byte[] bytes, int value) {
        writeInt(bytes, 0, value & 0xFFFFFFFF, ByteOrder.BIG_ENDIAN);
    }

    /**
     * 写入整型数到字节数组(4字节, 转为无符号)
     *
     * @param bytes 目标字节数组
     * @param value 写入值
     */
    public static void writeUnsignedInt(byte[] bytes, long value) {
        writeInt(bytes, 0, (int) (value & 0xFFFFFFFF), ByteOrder.BIG_ENDIAN);
    }

    /**
     * 写入整型数到字节数组(4字节, 转为无符号)
     *
     * @param bytes 目标字节数组
     * @param position 写入位置
     * @param value 写入值
     */
    public static void writeUnsignedInt(byte[] bytes, int position, short value) {
        writeInt(bytes, position, (int) (value & 0xFFFF), ByteOrder.BIG_ENDIAN);
    }

    /**
     * 写入整型数到字节数组(4字节, 转为无符号)
     *
     * @param bytes 目标字节数组
     * @param position 写入位置
     * @param value 写入值
     */
    public static void writeUnsignedInt(byte[] bytes, int position, int value) {
        writeInt(bytes, position, (int) (value & 0xFFFFFFFF), ByteOrder.BIG_ENDIAN);
    }

    /**
     * 写入整型数到字节数组(4字节, 转为无符号)
     *
     * @param bytes 目标字节数组
     * @param position 写入位置
     * @param value 写入值
     */
    public static void writeUnsignedInt(byte[] bytes, int position, long value) {
        writeInt(bytes, position, (int) (value & 0xFFFFFFFFL), ByteOrder.BIG_ENDIAN);
    }

    /**
     * 写入整型数到字节数组(4字节, 转为无符号)
     *
     * @param bytes 目标字节数组
     * @param value 写入值
     * @param order 大小端模式
     */
    public static void writeUnsignedInt(byte[] bytes, short value, ByteOrder order) {
        writeInt(bytes, 0, (int) (value & 0xFFFF), order);
    }

    /**
     * 写入整型数到字节数组(4字节, 转为无符号)
     *
     * @param bytes 目标字节数组
     * @param value 写入值
     * @param order 大小端模式
     */
    public static void writeUnsignedInt(byte[] bytes, int value, ByteOrder order) {
        writeInt(bytes, 0, (int) (value & 0xFFFFFFFF), order);
    }

    /**
     * 写入整型数到字节数组(4字节, 转为无符号)
     *
     * @param bytes 目标字节数组
     * @param value 写入值
     * @param order 大小端模式
     */
    public static void writeUnsignedInt(byte[] bytes, long value, ByteOrder order) {
        writeInt(bytes, 0, (int) (value & 0xFFFFFFFFL), order);
    }

    /**
     * 写入整型数到字节数组(4字节, 转为无符号)
     *
     * @param bytes 目标字节数组
     * @param position 写入位置
     * @param value 写入值
     * @param order 大小端模式
     */
    public static void writeUnsignedInt(byte[] bytes, int position, short value, ByteOrder order) {
        writeInt(bytes, position, (int) (value & 0xFFFF), order);
    }

    /**
     * 写入整型数到字节数组(4字节, 转为无符号)
     *
     * @param bytes 目标字节数组
     * @param position 写入位置
     * @param value 写入值
     * @param order 大小端模式
     */
    public static void writeUnsignedInt(byte[] bytes, int position, int value, ByteOrder order) {
        writeInt(bytes, position, (int) (value & 0xFFFFFFFF), order);
    }

    /**
     * 写入整型数到字节数组(4字节, 转为无符号)
     *
     * @param bytes 目标字节数组
     * @param position 写入位置
     * @param value 写入值
     * @param order 大小端模式
     */
    public static void writeUnsignedInt(byte[] bytes, int position, long value, ByteOrder order) {
        writeInt(bytes, position, (int) (value & 0xFFFFFFFFL), order);
    }

    /**
     * 短整型转字节数组(大端模式, 高字节在前)
     *
     * @param val 短整型值
     * @return 长度为 2 的字节数组
     */
    public static byte[] toBytes(short val) {
        return toBytes(val, ByteOrder.BIG_ENDIAN);
    }

    /**
     * 短整型转字节数组
     *
     * @param val 短整型值
     * @param order 大小端模式
     * @return 长度为 2 的字节数组
     */
    public static byte[] toBytes(short val, ByteOrder order) {
        byte[] b = new byte[SIZE_SHORT];
        if (ByteOrder.BIG_ENDIAN.equals(order)) {
            b[0] = (byte) (val >> 8);
            b[1] = (byte) val;
        } else {
            b[0] = (byte) val;
            b[1] = (byte) (val >> 8);
        }
        return b;
    }

    /**
     * 写入短整型数到字节数组(大端模式, 高字节在前)
     *
     * @param bytes 目标字节数组
     * @param value 写入值
     */
    public static void writeShort(byte[] bytes, short value) {
        writeShort(bytes, 0, value, ByteOrder.BIG_ENDIAN);
    }

    /**
     * 写入短整型数到字节数组(大端模式, 高字节在前)
     *
     * @param bytes 目标字节数组
     * @param position 写入位置
     * @param value 写入值
     */
    public static void writeShort(byte[] bytes, int position, short value) {
        writeShort(bytes, position, value, ByteOrder.BIG_ENDIAN);
    }

    /**
     * 写入短整型数到字节数组
     *
     * @param bytes 目标字节数组
     * @param position 写入位置
     * @param value 写入值
     * @param order 大小端模式
     */
    public static void writeShort(byte[] bytes, int position, short value, ByteOrder order) {
        if (ByteOrder.BIG_ENDIAN.equals(order)) {
            bytes[position + 0] = (byte) (value >> 8);
            bytes[position + 1] = (byte) (value);
        } else {
            bytes[position + 0] = (byte) (value);
            bytes[position + 1] = (byte) (value >> 8);
        }
    }

    /**
     * 写入短整型到字节数组(2字节，转为无符号)
     *
     * @param bytes 目标数组
     * @param value 写入值
     */
    public static void writeUnsignedShort(byte[] bytes, byte value) {
        writeShort(bytes, 0, (short) (value & 0xFFFF), ByteOrder.BIG_ENDIAN);
    }

    /**
     * 写入短整型到字节数组(2字节，转为无符号)
     *
     * @param bytes 目标数组
     * @param value 写入值
     */
    public static void writeUnsignedShort(byte[] bytes, short value) {
        writeShort(bytes, 0, (short) (value & 0xFFFF), ByteOrder.BIG_ENDIAN);
    }

    /**
     * 写入短整型到字节数组(2字节，转为无符号)
     *
     * @param bytes 目标数组
     * @param value 写入值
     */
    public static void writeUnsignedShort(byte[] bytes, int value) {
        writeShort(bytes, 0, (short) (value & 0xFFFF), ByteOrder.BIG_ENDIAN);
    }

    /**
     * 写入短整型到字节数组(2字节，转为无符号)
     *
     * @param bytes 目标数组
     * @param position 写入位置
     * @param value 写入值
     */
    public static void writeUnsignedShort(byte[] bytes, int position, byte value) {
        writeShort(bytes, position, (short) (value & 0xFFFF), ByteOrder.BIG_ENDIAN);
    }

    /**
     * 写入短整型到字节数组(2字节，转为无符号)
     *
     * @param bytes 目标数组
     * @param position 写入位置
     * @param value 写入值
     */
    public static void writeUnsignedShort(byte[] bytes, int position, short value) {
        writeShort(bytes, position, (short) (value & 0xFFFF), ByteOrder.BIG_ENDIAN);
    }

    /**
     * 写入短整型到字节数组(2字节，转为无符号)
     *
     * @param bytes 目标数组
     * @param value 写入值
     * @param order 大小端模式
     */
    public static void writeUnsignedShort(byte[] bytes, byte value, ByteOrder order) {
        writeShort(bytes, 0, (short) (value & 0xFFFF), order);
    }

    /**
     * 写入短整型到字节数组(2字节，转为无符号)
     *
     * @param bytes 目标数组
     * @param value 写入值
     * @param order 大小端模式
     */
    public static void writeUnsignedShort(byte[] bytes, int value, ByteOrder order) {
        writeShort(bytes, 0, (short) (value & 0xFFFF), order);
    }

    /**
     * 写入短整型到字节数组(2字节，转为无符号)
     *
     * @param bytes 目标数组
     * @param value 写入值
     * @param order 大小端模式
     */
    public static void writeUnsignedShort(byte[] bytes, short value, ByteOrder order) {
        writeShort(bytes, 0, (short) (value & 0xFFFF), order);
    }

    /**
     * 写入短整型到字节数组(2字节，转为无符号)
     *
     * @param bytes 目标数组
     * @param position 写入位置
     * @param value 写入值
     * @param order 大小端模式
     */
    public static void writeUnsignedShort(byte[] bytes, int position, byte value, ByteOrder order) {
        writeShort(bytes, position, (short) (value & 0xFFFF), order);
    }

    /**
     * 写入短整型到字节数组(2字节，转为无符号)
     *
     * @param bytes 目标数组
     * @param position 写入位置
     * @param value 写入值
     * @param order 大小端模式
     */
    public static void writeUnsignedShort(byte[] bytes, int position, short value, ByteOrder order) {
        writeShort(bytes, position, (short) (value & 0xFFFF), order);
    }

    /**
     * 写入短整型到字节数组(2字节，转为无符号)
     *
     * @param bytes 目标数组
     * @param position 写入位置
     * @param value 写入值
     * @param order 大小端模式
     */
    public static void writeUnsignedShort(byte[] bytes, int position, int value, ByteOrder order) {
        writeShort(bytes, position, (short) (value & 0xFFFF), order);
    }

    /**
     * 字节数组转短整型(大端模式, 高字节在前)
     *
     * @param b 字节数组
     * @return 短整型
     */
    public static short toShort(byte[] b) {
        return toShort(b, 0);
    }

    /**
     * 字节数组转短整型
     *
     * @param b 字节数组
     * @param order 大小端模式
     * @return 短整型
     */
    public static short toShort(byte[] b, ByteOrder order) {
        return toShort(b, 0, order);
    }

    /**
     * 字节数组转短整型(大端模式, 高字节在前)
     *
     * @param b 字节数组
     * @param offset 偏移量
     * @return 短整型
     */
    public static short toShort(byte[] b, int offset) {
        return toShort(b, offset, ByteOrder.BIG_ENDIAN);
    }

    /**
     * 字节数组转短整型
     *
     * @param b 字节数组
     * @param offset 偏移量
     * @param order 大小端模式
     * @return 短整型
     */
    public static short toShort(byte[] b, int offset, ByteOrder order) {
        if (ByteOrder.BIG_ENDIAN.equals(order)) {
            return (short) (((b[offset + 0] & 0xff) << 8) | (b[offset + 1] & 0xff));
        } else {
            return (short) ((b[offset + 0] & 0xff) | ((b[offset + 1] & 0xff) << 8));
        }
    }

    /**
     * 字节数组转短整型(大端模式, 高字节在前)(无符号)
     *
     * @param b 字节数组
     * @return 整型
     */
    public static int toUnsignedShort(byte[] b) {
        return toShort(b, 0) & 0xFFFF;
    }

    /**
     * 字节数组转短整型(无符号)
     *
     * @param b 字节数组
     * @param order 大小端模式
     * @return 整型
     */
    public static int toUnsignedShort(byte[] b, ByteOrder order) {
        return toShort(b, order) & 0xFFFF;
    }

    /**
     * 字节数组转短整型(大端模式, 高字节在前)(无符号)
     *
     * @param b 字节数组
     * @param offset 偏移量
     * @return 整型
     */
    public static int toUnsignedShort(byte[] b, int offset) {
        return toShort(b, offset) & 0xFFFF;
    }

    /**
     * 字节数组转短整型(无符号)
     *
     * @param b 字节数组
     * @param offset 偏移量
     * @param order 大小端模式
     * @return 整型
     */
    public static int toUnsignedShort(byte[] b, int offset, ByteOrder order) {
        return toShort(b, offset, order) & 0xFFFF;
    }

    /**
     * 浮点数转字节数组(大端模式, 高字节在前)
     *
     * @param val 浮点值
     * @return 长度为 4 的字节数组
     */
    public static byte[] toBytes(float val) {
        return toBytes(Float.floatToIntBits(val));
    }

    /**
     * 浮点数转字节数组
     *
     * @param val 浮点值
     * @param order 大小端模式
     * @return 长度为 4 的字节数组
     */
    public static byte[] toBytes(float val, ByteOrder order) {
        return toBytes(Float.floatToIntBits(val), order);
    }

    /**
     * 写入浮点数到字节数组(大端模式, 高字节在前)
     *
     * @param bytes 目标字节数组
     * @param position 写入位置
     * @param value 写入值
     */
    public static void writeFloat(byte[] bytes, int position, float value) {
        writeFloat(bytes, position, value, ByteOrder.BIG_ENDIAN);
    }

    /**
     * 写入浮点数到字节数组(大端模式, 高字节在前)
     *
     * @param bytes 目标字节数组
     * @param position 写入位置
     * @param value 写入值
     * @param order 大小端模式
     */
    public static void writeFloat(byte[] bytes, int position, float value, ByteOrder order) {
        int intBits = Float.floatToIntBits(value);
        if (ByteOrder.BIG_ENDIAN.equals(order)) {
            bytes[position + 0] = (byte) ((intBits >> 24) & 0xFF);
            bytes[position + 1] = (byte) ((intBits >> 16) & 0xFF);
            bytes[position + 2] = (byte) ((intBits >> 8) & 0xFF);
            bytes[position + 3] = (byte) ((intBits) & 0xFF);
        } else {
            bytes[position + 0] = (byte) ((intBits) & 0xFF);
            bytes[position + 1] = (byte) ((intBits >> 8) & 0xFF);
            bytes[position + 2] = (byte) ((intBits >> 16) & 0xFF);
            bytes[position + 3] = (byte) ((intBits >> 24) & 0xFF);
        }
    }

    /**
     * 字节数组转浮点数(大端模式, 高字节在前)
     *
     * @param b 字节数组
     * @return 浮点值
     */
    public static float toFloat(byte[] b) {
        return toFloat(b, 0);
    }

    /**
     * 字节数组转浮点数
     *
     * @param b 字节数组
     * @param order 大小端模式
     * @return 浮点值
     */
    public static float toFloat(byte[] b, ByteOrder order) {
        return toFloat(b, 0, order);
    }

    /**
     * 字节数组转浮点数(大端模式, 高字节在前)
     *
     * @param b 字节数组
     * @param offset 偏移量
     * @return 浮点值
     */
    public static float toFloat(byte[] b, int offset) {
        return Float.intBitsToFloat(toInt(b, offset));
    }

    /**
     * /** 字节数组转浮点数
     *
     * @param b 字节数组
     * @param offset 偏移量
     * @param order 大小端模式
     * @return 浮点值
     */
    public static float toFloat(byte[] b, int offset, ByteOrder order) {
        return Float.intBitsToFloat(toInt(b, offset, order));
    }

    /**
     * IP 地址转为4字节数组
     *
     * @param ip IP地址整型
     * @return 4字节数组
     */
    public static byte[] ipToBytes(long ip) {
        byte[] b = new byte[SIZE_INT];
        b[0] = (byte) (ip >> 24 & 0xff);
        b[1] = (byte) (ip >> 16 & 0xff);
        b[2] = (byte) (ip >> 8 & 0xff);
        b[3] = (byte) (ip & 0xff);
        return b;
    }

    /**
     * 长整型装字节数组(大端模式, 高字节在前)
     *
     * @param val 长整型值
     * @return 长度为 8 的字节数组
     */
    public static byte[] toBytes(long val) {
        return toBytes(val, ByteOrder.BIG_ENDIAN);
    }

    /**
     * 长整型装字节数组
     *
     * @param val 长整型值
     * @param order 大小端模式
     * @return 长度为 8 的字节数组
     */
    public static byte[] toBytes(long val, ByteOrder order) {
        byte[] b = new byte[SIZE_LONG];
        if (ByteOrder.BIG_ENDIAN.equals(order)) {
            b[0] = (byte) (val >> 56);
            b[1] = (byte) (val >> 48);
            b[2] = (byte) (val >> 40);
            b[3] = (byte) (val >> 32);
            b[4] = (byte) (val >> 24);
            b[5] = (byte) (val >> 16);
            b[6] = (byte) (val >> 8);
            b[7] = (byte) val;
        } else {
            b[0] = (byte) (val);
            b[1] = (byte) (val >> 8);
            b[2] = (byte) (val >> 16);
            b[3] = (byte) (val >> 24);
            b[4] = (byte) (val >> 32);
            b[5] = (byte) (val >> 40);
            b[6] = (byte) (val >> 48);
            b[7] = (byte) (val >> 56);
        }
        return b;
    }

    /**
     * 写入长整型数到字节数组(大端模式, 高字节在前)
     *
     * @param bytes 目标字节数组
     * @param value 写入值
     */
    public static void writeLong(byte[] bytes, long value) {
        writeLong(bytes, 0, value, ByteOrder.BIG_ENDIAN);
    }

    /**
     * 写入长整型数到字节数组(大端模式, 高字节在前)
     *
     * @param bytes 目标字节数组
     * @param value 写入值
     * @param order 大小端模式
     */
    public static void writeLong(byte[] bytes, long value, ByteOrder order) {
        writeLong(bytes, 0, value, order);
    }

    /**
     * 写入长整型数到字节数组(大端模式, 高字节在前)
     *
     * @param bytes 目标字节数组
     * @param position 写入位置
     * @param value 写入值
     */
    public static void writeLong(byte[] bytes, int position, long value) {
        writeLong(bytes, position, value, ByteOrder.BIG_ENDIAN);
    }

    /**
     * 写入长整型数到字节数组
     *
     * @param bytes 目标字节数组
     * @param position 写入位置
     * @param value 写入值
     * @param order 大小端模式
     */
    public static void writeLong(byte[] bytes, int position, long value, ByteOrder order) {
        if (ByteOrder.BIG_ENDIAN.equals(order)) {
            bytes[position + 0] = (byte) ((value >> 56) & 0xFF);
            bytes[position + 1] = (byte) ((value >> 48) & 0xFF);
            bytes[position + 2] = (byte) ((value >> 40) & 0xFF);
            bytes[position + 3] = (byte) ((value >> 32) & 0xFF);
            bytes[position + 4] = (byte) ((value >> 24) & 0xFF);
            bytes[position + 5] = (byte) ((value >> 16) & 0xFF);
            bytes[position + 6] = (byte) ((value >> 8) & 0xFF);
            bytes[position + 7] = (byte) ((value) & 0xFF);
        } else {
            bytes[position + 0] = (byte) ((value) & 0xFF);
            bytes[position + 1] = (byte) ((value >> 8) & 0xFF);
            bytes[position + 2] = (byte) ((value >> 16) & 0xFF);
            bytes[position + 3] = (byte) ((value >> 24) & 0xFF);
            bytes[position + 4] = (byte) ((value >> 32) & 0xFF);
            bytes[position + 5] = (byte) ((value >> 40) & 0xFF);
            bytes[position + 6] = (byte) ((value >> 48) & 0xFF);
            bytes[position + 7] = (byte) ((value >> 56) & 0xFF);
        }
    }

    /**
     * 字节数组转长整型(大端模式, 高字节在前)
     *
     * @param b 字节数组
     * @return 长整型
     */
    public static long toLong(byte[] b) {
        return toLong(b, 0);
    }

    /**
     * 字节数组转长整型
     *
     * @param b 字节数组
     * @param order 大小端模式
     * @return 长整型
     */
    public static long toLong(byte[] b, ByteOrder order) {
        return toLong(b, 0, order);
    }

    /**
     * 字节数组转长整型(大端模式, 高字节在前)
     *
     * @param b 字节数组
     * @param offset 偏移量
     * @return 长整型
     */
    public static long toLong(byte[] b, int offset) {
        return toLong(b, offset, ByteOrder.BIG_ENDIAN);
    }

    /**
     * 字节数组转长整型
     *
     * @param b 字节数组
     * @param offset 偏移量
     * @param order 大小端模式
     * @return 长整型
     */
    public static long toLong(byte[] b, int offset, ByteOrder order) {
        if (ByteOrder.BIG_ENDIAN.equals(order)) {
            return ((b[offset] & 0xffL) << 56) | ((b[offset + 1] & 0xffL) << 48) | ((b[offset + 2] & 0xffL) << 40)
                    | ((b[offset + 3] & 0xffL) << 32) | ((b[offset + 4] & 0xffL) << 24)
                    | ((b[offset + 5] & 0xffL) << 16) | ((b[offset + 6] & 0xffL) << 8) | (b[offset + 7] & 0xffL);
        } else {
            return (b[offset] & 0xffL) | ((b[offset + 1] & 0xffL) << 8) | ((b[offset + 2] & 0xffL) << 16)
                    | ((b[offset + 3] & 0xffL) << 24) | ((b[offset + 4] & 0xffL) << 32)
                    | ((b[offset + 5] & 0xffL) << 40) | ((b[offset + 6] & 0xffL) << 48)
                    | ((b[offset + 7] & 0xffL) << 56);
        }
    }

    /**
     * 双精度浮点转字节数组(大端模式, 高字节在前)
     *
     * @param val 双精度浮点
     * @return 长度为 8 的字节数组
     */
    public static byte[] toBytes(double val) {
        return toBytes(Double.doubleToLongBits(val));
    }

    /**
     * 双精度浮点转字节数组
     *
     * @param val 双精度浮点
     * @param order 大小端模式
     * @return 长度为 8 的字节数组
     */
    public static byte[] toBytes(double val, ByteOrder order) {
        return toBytes(Double.doubleToLongBits(val), order);
    }

    /**
     * 写入双精度浮点数到字节数组(大端模式, 高字节在前)
     *
     * @param bytes 目标字节数组
     * @param position 写入位置
     * @param value 写入值
     */
    public static void writeDouble(byte[] bytes, int position, double value) {
        writeDouble(bytes, position, value, ByteOrder.BIG_ENDIAN);
    }

    /**
     * 写入双精度浮点数到字节数组
     *
     * @param bytes 目标字节数组
     * @param position 写入位置
     * @param value 写入值
     * @param order 大小端模式
     */
    public static void writeDouble(byte[] bytes, int position, double value, ByteOrder order) {
        long longBits = Double.doubleToLongBits(value);
        if (ByteOrder.BIG_ENDIAN.equals(order)) {
            bytes[position + 0] = (byte) ((longBits >> 56) & 0xFF);
            bytes[position + 1] = (byte) ((longBits >> 48) & 0xFF);
            bytes[position + 2] = (byte) ((longBits >> 40) & 0xFF);
            bytes[position + 3] = (byte) ((longBits >> 32) & 0xFF);
            bytes[position + 4] = (byte) ((longBits >> 24) & 0xFF);
            bytes[position + 5] = (byte) ((longBits >> 16) & 0xFF);
            bytes[position + 6] = (byte) ((longBits >> 8) & 0xFF);
            bytes[position + 7] = (byte) ((longBits) & 0xFF);
        } else {
            bytes[position + 0] = (byte) ((longBits) & 0xFF);
            bytes[position + 1] = (byte) ((longBits >> 8) & 0xFF);
            bytes[position + 2] = (byte) ((longBits >> 16) & 0xFF);
            bytes[position + 3] = (byte) ((longBits >> 24) & 0xFF);
            bytes[position + 4] = (byte) ((longBits >> 32) & 0xFF);
            bytes[position + 5] = (byte) ((longBits >> 40) & 0xFF);
            bytes[position + 6] = (byte) ((longBits >> 48) & 0xFF);
            bytes[position + 7] = (byte) ((longBits >> 56) & 0xFF);
        }
    }

    /**
     * 字节数组转双精度浮点(大端模式, 高字节在前)
     *
     * @param b 字节数组
     * @return 双精度浮点
     */
    public static double toDouble(byte[] b) {
        return toDouble(b, 0);
    }

    /**
     * 字节数组转双精度浮点
     *
     * @param b 字节数组
     * @param order 大小端模式
     * @return 双精度浮点
     */
    public static double toDouble(byte[] b, ByteOrder order) {
        return toDouble(b, 0, order);
    }

    /**
     * 字节数组转双精度浮点(大端模式, 高字节在前)
     *
     * @param b 字节数组
     * @param offset 偏移量
     * @return 双精度浮点
     */
    public static double toDouble(byte[] b, int offset) {
        return Double.longBitsToDouble(toLong(b, offset));
    }

    /**
     * 字节数组转双精度浮点
     *
     * @param b 字节数组
     * @param offset 偏移量
     * @param order 大小端模式
     * @return 双精度浮点
     */
    public static double toDouble(byte[] b, int offset, ByteOrder order) {
        return Double.longBitsToDouble(toLong(b, offset, order));
    }

    /**
     * 写入字节数组到目标字节数组
     *
     * @param destBytes 目标字节数组
     * @param position 写入位置
     * @param value 写入数组
     */
    public static void writeBytes(byte[] destBytes, int position, byte[] value) {
        System.arraycopy(value, 0, destBytes, position, value.length);
    }

    /**
     * 反转字节数组
     *
     * @param array 源字节数组
     * @return 翻转后的字节数组
     */
    public static byte[] reverse(byte[] array) {
        if (array == null) {
            return new byte[0];
        }
        return reverse(array, 0, array.length);
    }

    /**
     * 反转字节数组
     *
     * @param array 源字节数组
     * @param startIndexInclusive 开始反转的位置（含）
     * @param endIndexExclusive 结束反转的位置（不含）
     * @return 翻转后的字节数组
     */
    public static byte[] reverse(byte[] array, int startIndexInclusive, int endIndexExclusive) {
        if (array == null) {
            return new byte[0];
        }
        byte[] arrayDuplicate = ByteUtil.subBytes(array, 0);
        int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
        int j = Math.min(arrayDuplicate.length, endIndexExclusive) - 1;
        byte tmp;
        while (j > i) {
            tmp = arrayDuplicate[j];
            arrayDuplicate[j] = arrayDuplicate[i];
            arrayDuplicate[i] = tmp;
            j--;
            i++;
        }
        return arrayDuplicate;
    }

    public static List<byte[]> split(byte[] array, byte value) {
        List<byte[]> list = new ArrayList<byte[]>();
        List<Byte> subList = new ArrayList<Byte>();
        for (byte element : array) {
            if (element == value && !subList.isEmpty()) {
                list.add(convertToPrimitiveArray(subList));
                subList = new ArrayList<Byte>();
            } else if (element != value) {
                subList.add(element);
            }
        }
        if (!subList.isEmpty()) {
            list.add(convertToPrimitiveArray(subList));
        }
        return list;
    }

    public static List<byte[]> splitKeyValue(byte[] array, byte value) {
        List<byte[]> list = new ArrayList<byte[]>();
        int index = indexOf(array, new byte[]{value});
        if (index != -1) {
            list.add(subBytes(array, 0, index));
            list.add(subBytes(array, index + 1));
        } else {
            list.add(array);
        }
        return list;
    }

    private static byte[] convertToPrimitiveArray(List<Byte> list) {
        byte[] array = new byte[list.size()];
        for (int i = 0; i < list.size(); i++) {
            array[i] = list.get(i);
        }
        return array;
    }

    public static short getUnsigned(byte data) {
        return (short) (data & 0xFF);
    }

    public static int getUnsigned(short data) {
        return data & 0xFFFF;
    }

    public static long getUnsigned(int data) {
        return data & 0xFFFFFFFF;
    }

    /**
     * 压缩字节数组
     *
     * @param array 源字节数组
     * @return 压缩后的字节数组
     */
    public static byte[] compress(byte[] array) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream(array.length);
        Deflater compressor = new Deflater();
        try {
            compressor.setLevel(Deflater.BEST_COMPRESSION);
            compressor.setInput(array, 0, array.length);
            compressor.finish();
            // Compress the data
            byte[] buf = new byte[1024];
            while (!compressor.finished()) {
                int count = compressor.deflate(buf);
                bos.write(buf, 0, count);
            }
        } finally {
            compressor.end();
        }
        return bos.toByteArray();
    }

    /**
     * 解压字节数组
     *
     * @param compressed 压缩的字节数组
     * @return 解压后的字节数组
     * @throws DataFormatException 压缩数据格式无效
     */
    public static byte[] decompress(byte[] compressed) throws DataFormatException {
        return decompress(compressed, 0, compressed.length);
    }

    /**
     * 解压字节数组
     *
     * @param compressed 压缩的字节数组
     * @param offset 开始位置
     * @param length 读取长度
     * @return 解压后的字节数组
     * @throws DataFormatException 压缩数据格式无效
     */
    public static byte[] decompress(byte[] compressed, int offset, int length) throws DataFormatException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream(length);
        Inflater deCompressor = new Inflater();
        try {
            deCompressor.setInput(compressed, offset, length);
            // Decompress the data
            byte[] buf = new byte[1024];
            while (!deCompressor.finished()) {
                int count = deCompressor.inflate(buf);
                bos.write(buf, 0, count);
            }
        } finally {
            deCompressor.end();
        }
        return bos.toByteArray();
    }

    /**
     * byte[] 转为 对象
     *
     * @param bytes 字节数组
     * @return 对象
     */
    public static Object byteToObject(byte[] bytes) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
            return ois.readObject();
        } finally {
            if (ois != null) {
                ois.close();
            }
        }
    }

    /**
     * 对象 转为 byte[]
     *
     * @param obj 对象
     * @return 字节数组
     */
    public static byte[] objectToByte(Object obj) throws IOException, ClassNotFoundException {
        ObjectOutputStream oos = null;
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(obj);
            return bos.toByteArray();
        } finally {
            if (oos != null) {
                oos.close();
            }
        }
    }

    /**
     * 4字节数组变形， 用 ACBD 表示转换后的字节序， pattern 表示当前的字节序
     *
     * @param bytes
     * @param pattern 字节序，用 ACBD 表示
     * @return
     */
    public static byte[] convert(byte[] bytes, String pattern) {
        byte[] result = new byte[4];
        for (int i = 0; i < 4; i++) {
            char p = pattern.charAt(i);
            switch (p) {
                case 'A':
                    result[0] = bytes[i];
                    break;
                case 'B':
                    result[1] = bytes[i];
                    break;
                case 'C':
                    result[2] = bytes[i];
                    break;
                case 'D':
                    result[3] = bytes[i];
                    break;
                default:
                    throw new RuntimeException("illegal pattern.");
            }
        }
        return result;
    }
}
